<template>
 <!-- css采用BEM规范 Block表示组件名:slider Element表示元素:item ,Block和Element之间使用双下划线__连接 -->
 <!-- 可扩展性和可复用性，则对于整个项目的未来有很大的帮助，是对高级工程师的要求。在前端UI组件中，提升可扩展性的基本思路，是插件化 -->
 <!-- 它的插件化可以是将用户控制组件从Slider组件中剥离出来，做成插件，这样才能提高Slider组件的可扩展性 -->

  <div class="slider">
    <ul>
      <li class="slider__item--selected">
        <img :src="getImageUrl('1.png')">
      </li>
      <li class="slider__item">
        <img :src="getImageUrl('2.jpg')">
      </li>
      <li class="slider__item">
        <img :src="getImageUrl('3.jpg')">
      </li>
      <li class="slider__item">
        <img :src="getImageUrl('4.jpg')">
      </li>
    </ul>
    <a class="slider__next"></a>
    <a class="slider__previous"></a>
    <div class="slider__control">
      <span class="slider__control-buttons--selected"></span>
      <span class="slider__control-buttons"></span>
      <span class="slider__control-buttons"></span>
      <span class="slider__control-buttons"></span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, reactive,ref } from 'vue'
/**
 * 1.设计HTML结构
 * 2.设计组件的API：
 *   a.slidoTo(idx)-切换显示idx指示位置的图片 
 *   b.slideNext()-切换到下一张图
 *   c.slidePrevious()-切换到上一张图
 *   d.getSelectedItem()-获取选中的图片
 *   e.getSelectedItemIndex()-获取选中的图片位置
 * 3.设计用户控制流程
 */

  // js函数，放src目录下
  const getImageUrl = (url: string) => {
    return new URL(`../assets/images/slider/${url}`, import.meta.url).href;
  }

  // 获取选中图片
  const getSelectedItem = () =>{
    const selected = document.querySelector(".slider__item--selected")
    console.log('获取选中的图片',selected);
    return selected
  }

  //获取选中的元素在items数组中的位置
  const getSelectedItemIndex = () =>{
    return items.indexOf(getSelectedItem())
  }

  const slideTo = (idx) => {
    const selected = getSelectedItem();
    if(selected) {
      selected.className = 'slider__item'
    }
    const item = items[idx]

    if(item) { // 将当前选中的图片标记为选中状态
      item.className = 'slider__item--selected';
    }

    const detail = {index: idx};
    const event = new CustomEvent('slide', {bubbles: true, detail}); // 这个自定义事件（CustomEvent），它的作用是让底部小圆点控件监听slideTo方法
    document.dispatchEvent(event); 
  }

  /**
   * 将下一张图片标记为选中状态
   */
  const slideNext = () => {
    const currentIdx = getSelectedItemIndex();
    console.log('slideNext的当前idx',currentIdx);
    const nextIdx = ( currentIdx + 1 ) % items.length
    slideTo(nextIdx)
  }

  /**
   * 将上一张图片标记为选中状态
   */
  const slidePrevious = () => {
    const currentIdx = getSelectedItemIndex()
    const previousIdx = (items.length + currentIdx - 1 ) % items.length
    slideTo(previousIdx)
  }

  /**
   * 点击上一张或下一张事件
   */
  const pluginPrevious = () => {
    const previous = document.querySelector('.slider__previous');
    previous?.addEventListener("click", evt => { //提示：Object is possibly 'null', 解决方法: ?.
      stop()
      slidePrevious()
      start()
      evt.preventDefault()
    })
  }

  const pluginNext = () => {
    const next = document.querySelector('.slider__next');
    next?.addEventListener('click', evt => {
      stop();
      slideNext();
      start();
      evt.preventDefault();
    });
  }

  /**
   * 当鼠标移入或移出小圆点事件
   */
  const pluginController = () =>{
    const bts= document.querySelectorAll(".slider__control-buttons, .slider__control-buttons--selected")
    const buttons:Array<any> = Array.from(bts)

    const  controller =  document.querySelector<HTMLElement>(".slider__control")
    console.log('使用document.querySelector获取值:',controller);

    /**
     * 注册slide事件，将选中的图片和小圆点设置为selected状态
     * 处理一个自定义事件 —— slide事件
     */
    document.addEventListener('slide',(evt) =>{
      console.log('自定义事件：', evt.detail); // 输出的结果：{index: 1}
      const idx = evt.detail.index
      console.log('将选中的图片和小圆点设置为selected状态的下标',idx);
      const selected  = controller?.querySelector('.slider__control-buttons--selected')
      if(selected) selected.className = 'slider__control-buttons'
      buttons[idx].className = 'slider__control-buttons--selected'
    })

    controller?.addEventListener('touchstart',(evt) => {
      const idx = buttons.indexOf(evt.target)
      if(idx >= 0){
        slideTo(idx)
        stop() // 判断当前选中的是第几个小圆点，停止自动循环播放功能，然后切换到对应的图片
      }
    })

    controller?.addEventListener('touchend',(evt) => {
      start() // 重启自动循环播放功能
    })
  }

  let items:Array<any> = reactive([])
  const cycle:number = 3000
  let _timer: any //定义全局变量

  const start = () => {
    stop()
    _timer = setInterval(() => {
      slideNext();
    },cycle)
  }

  const stop = () => {
    clearInterval(_timer) // clearInterval(timer)时参数类型会出问题，所以要将参数强制转换成number型
  }

 
  onMounted(() =>{
    const doms = document.querySelectorAll(".slider__item, .slider__item--selected")
    items = Array.from(doms)
    
    //开始执行
    start()
    pluginPrevious()
    pluginNext()
    pluginController()

  })

</script>
<style lang="scss" scoped>
.slider {
  position: relative;
  width:100%;
  height: 161px;
  ul {
    list-style-type: none;
    position: relative;
    width:100%;
    height: 100%;
    padding: 0;
    margin: 0;
  }
  .slider__item,.slider__item--selected {
    position: absolute;
    transition: opacity 1s; // 设置图片透明度变化的动画，时间为1秒
    opacity: 0;
    text-align: center;
    img {
      width: 375px;
    }
  }
  .slider__item--selected {
    transition: opacity 1s;
    opacity: 1;
  }
  .slider__next,.slider__previous {
    display: inline-block;
    position: absolute;
    top:50%;//定位轮播图组件的纵向中间的位置
    margin-top: -25px;
    width:30px;
    height: 50px;
    line-height: 50px;
    text-align: center;
    overflow: hidden;
    border: none;
    color: #fff;
    font-size: 18px;
    background: rgba(0,0,0,0.2); /*设置为半透明*/;
    cursor: pointer;
    opacity: 1; //初始状态为透明,目前为移动端模式
    transition: opacity .5s;/*设置透明度变化的动画，时间为.5秒*/
  }
  .slider__previous {
    left: 0; /*定位在slider元素的最左边*/
  }

  .slider__next {
    right: 0; /*定位在slider元素的最右边*/
  }
 .slider__previous::after {
   content: "<";
 }

 .slider__next::after {
   content: ">";
 }
  
  .slider__control {
    position: relative;
    display: table; //table布局
    // background-color: rgba(255, 255, 255, 0.5);
    // padding: 5px;
    border-radius: 12px;
    bottom: 22px;
    margin: auto;
  }

  .slider__control-buttons,.slider__control-buttons--selected {
    display: inline-block;
    width:15px;
    height: 15px;
    border-radius: 50%;
    margin: 0 5px;
    background-color: #fff;
    cursor: pointer;
  }
  .slider__control-buttons--selected {
    background-color: red;
  }

}
//  .slider:hover .slider__previous {
//    opacity: 1;
//  }
//  .slider:hover .slider__next {
//    opacity: 1;
//  }
</style>